package controller

import (
	"excel/dao/mysql"
	"excel/logic"
	"fmt"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"strings"

	"go.uber.org/zap"

	"github.com/gin-gonic/gin"
	"github.com/xuri/excelize/v2"
)

// ToExcel 传入 Excel 表格的数据，处理后存入到 activity 表中
func ToExcel(ctx *gin.Context) {
	err := logic.DeleteTempFiles()
	if err != nil {
		return
	}
	// 1. 获取上传的 Excel 文件
	fileHeader, err := ctx.FormFile("excel")
	if err != nil {
		zap.L().Error("保存上传文件失败", zap.Error(err))
		ResponseErrorWithMsg(ctx, 400, fmt.Sprintf("保存文件失败: %v", err))

		return
	}

	// 保存上传的文件
	filePath := "./uploads/" + fileHeader.Filename
	if err := ctx.SaveUploadedFile(fileHeader, filePath); err != nil {
		zap.L().Error("保存上传文件失败", zap.Error(err))
		ResponseError(ctx, CodeServerBusy)
		return
	}

	if err := mysql.DeleteAllAndInsertActivity(); err != nil {
		zap.L().Error("清空数据库失败", zap.Error(err))
		ResponseErrorWithMsg(ctx, 500, fmt.Sprintf("清空数据库失败: %v", err))

		return
	}

	// 2. 根据文件扩展名选择解析方式
	ext := filepath.Ext(filePath)
	var rows [][]string

	if ext == ".xlsx" {
		f, err := excelize.OpenFile(filePath)
		if err != nil {
			zap.L().Error("打开 Excel 文件失败", zap.Error(err))
			ResponseError(ctx, CodeServerBusy)
			return
		}
		rows, err = f.GetRows(f.GetSheetName(0))
		if err != nil {
			zap.L().Error("读取 Excel 行失败", zap.Error(err))
			ResponseError(ctx, CodeServerBusy)
			return
		}
	} else {
		ResponseError(ctx, CodeInvalidParams)
		return
	}

	// 检查并删除全部为空的行
	for i := len(rows) - 1; i >= 0; i-- {
		isEmpty := true
		for _, cell := range rows[i] {
			if strings.TrimSpace(cell) != "" {
				isEmpty = false
				break
			}
		}
		if isEmpty {
			rows = append(rows[:i], rows[i+1:]...) // 删除该行
		}
	}

	// 检查表头
	if len(rows) > 0 && !strings.Contains(strings.ToLower(rows[0][0]), "title") {
		rows = rows[1:] // 删除第一行
	}
	if len(rows) > 0 && !strings.Contains(strings.ToLower(rows[0][0]), "title") {
		// 如果第一行第一列不是 "title"，则删除所有行的第一列
		for i := range rows {
			if len(rows[i]) > 0 {
				rows[i] = append(rows[i][:0], rows[i][1:]...) // 删除第一列
			}
		}
	}
	// 遍历并处理每一行数据
	var activities []mysql.Activity
	for index, row := range rows[2:] {
		if len(row) > 1 && (row[2] == "XX" || row[2] == "") {
			continue
		}
		activity := mysql.Activity{Title: logic.CleanTitle(row[0])}

		// 其他字段赋值
		if err := assignActivityFields(&activity, row, index, ctx); err != nil {
			return
		}

		// 将活动数据插入数据库
		if err := mysql.InsertActivity(activity); err != nil {
			zap.L().Error("数据插入数据库失败", zap.Error(err))
			ResponseError(ctx, CodeServerBusy)
			return
		}
		activities = append(activities, activity) // 存储活动数据
	}

	if err := logic.GenerateExcel(fileHeader.Filename); err != nil {
		zap.L().Error("生成 Excel 失败", zap.Error(err))
		ResponseError(ctx, CodeServerBusy)
		return
	}

	imgPaths, err := saveUploadedImages(ctx)
	if err != nil {
		return
	}
	if err := logic.GenerateImgExcel("图集"+fileHeader.Filename, activities, imgPaths); err != nil {
		ctx.String(http.StatusInternalServerError, "Failed to generate Excel: %s", err)
		return
	}

	//ctx.String(http.StatusOK, "Excel 文件已成功创建！")

	ResponseSuccess(ctx, nil)
}

// assignActivityFields 处理活动字段赋值及校验
func assignActivityFields(activity *mysql.Activity, row []string, index int, ctx *gin.Context) error {
	var err error

	if len(row) > 1 {
		activity.Manager = row[1]
	}
	if len(row) > 2 {
		activity.Mobile = row[2]
	}
	if len(row) > 3 {
		activity.ActiveBeginDate, err = logic.NormalizeDate(row[3])
		if err != nil {
			ResponseErrorWithMsg(ctx, 400, fmt.Sprintf("第 %d 行活动开始时间格式错误: %v, 行数据: %v", index+3, err, row))
			return err
		}
	}
	if len(row) > 4 {
		activity.ActiveEndDate, err = logic.NormalizeDate(row[4])
		if err != nil {
			ResponseErrorWithMsg(ctx, 400, fmt.Sprintf("第 %d 行活动结束时间格式错误: %v, 行数据: %v", index+3, err, row))
			return err
		}
	}
	if len(row) > 5 {
		activity.StartDate, err = logic.NormalizeDate(row[5])
		if err != nil {
			ResponseErrorWithMsg(ctx, 400, fmt.Sprintf("第 %d 行报名开始时间格式错误: %v, 行数据: %v", index+3, err, row))
			return err
		}
	}
	if len(row) > 6 {
		activity.EndDate, err = logic.NormalizeDate(row[6])
		if err != nil {
			ResponseErrorWithMsg(ctx, 400, fmt.Sprintf("第 %d 行报名结束时间格式错误: %v, 行数据: %v", index+3, err, row))
			return err
		}
	}
	// 校验时间顺序
	if !logic.ValidateDateOrder(activity) {
		ResponseErrorWithMsg(ctx, 400, fmt.Sprintf("第 %d 行时间顺序错误", index+3))
		return err
	}
	// 处理活动类型字段
	if len(row) > 7 {
		activity.Type, err = logic.NormalizeActivityType(row[7])
		if err != nil {
			ResponseErrorWithMsg(ctx, 400, fmt.Sprintf("第 %d 行活动类型错误: %v", index+3, err))
			return err
		}
	}

	// 处理其他字段
	assignAdditionalFields(activity, row)
	return nil
}

// assignAdditionalFields 处理额外字段赋值
func assignAdditionalFields(activity *mysql.Activity, row []string) {
	if len(row) > 8 {
		activity.Form = row[8]
	}
	if len(row) > 9 {
		activity.ServiceObject = row[9]
	}
	if len(row) > 10 {
		activity.Content = row[10]
	}
	if len(row) > 11 {
		activity.Street = row[11]
	}
	if len(row) > 12 {
		activity.Neighborhood = row[12]
	}
	if len(row) > 13 {
		activity.Address = row[13]
	}
	if len(row) > 14 {
		activity.Total, _ = logic.ParseVolunteerCount(row[14])
	}
	if len(row) > 15 {
		activity.MinNum, _ = logic.ParseVolunteerCount(row[15])
		if activity.MinNum > activity.Total {
			activity.MinNum = activity.Total
		}
		activity.Join = activity.MinNum
	}

	if len(row) > 16 {
		var err error
		activity.Organizer, err = logic.CleanOrganizer(row[16], &activity.Street, &activity.Neighborhood)
		if err != nil {
			// 处理错误，例如记录日志或返回特定错误信息
			fmt.Println("Error cleaning organizer:", err)

			return // 根据需要选择是否继续或返回
		}
	}
	if len(row) > 17 {
		activity.VolunteerLeader = row[17]
	}
	if len(row) > 18 {
		activity.VolLeaderTel = row[18]
	}
	if len(row) > 19 {
		activity.VolunteerNum = row[19]
	}
	if len(row) > 20 {
		activity.VolunteerOrganizer = row[20]
	}

	if len(row) > 22 {
		activity.PublicizeVolunteers = row[22]
	}
	if len(row) > 23 {
		activity.Status = row[23]
	}
	if len(row) > 24 {
		activity.PracticeVolunteers = row[24]
	}
	if len(row) > 25 {
		activity.Persons, _ = logic.ParseVolunteerCountString(row[25])
	}
	if len(row) > 26 {
		activity.Num, _ = logic.ParseVolunteerCountString(row[26])
	}
}

func saveUploadedImages(ctx *gin.Context) ([]string, error) {
	if err := ctx.Request.ParseMultipartForm(0); err != nil {
		return nil, fmt.Errorf("failed to parse form: %w", err)
	}
	// 获取图片文件列表
	files := ctx.Request.MultipartForm.File["imgs"]
	var imgPaths []string

	for i, fileHeaders := range files {
		// 保存图片到临时文件
		file, err := fileHeaders.Open()
		if err != nil {
			return nil, fmt.Errorf("failed to open file: %w", err)
		}
		defer file.Close()

		// 生成新的文件名
		tempFileName := fmt.Sprintf("%d.jpg", i+1) // 按顺序命名为 1.jpg, 2.jpg, ...
		tempFilePath := fmt.Sprintf("./temp/%s", tempFileName)

		out, err := os.Create(tempFilePath)
		if err != nil {
			return nil, fmt.Errorf("failed to create temp file: %w", err)
		}
		defer out.Close()

		// 复制文件内容
		if _, err := io.Copy(out, file); err != nil {
			return nil, fmt.Errorf("failed to copy file: %w", err)
		}

		imgPaths = append(imgPaths, tempFilePath) // 保存路径
	}

	return imgPaths, nil
}
